import datetime

from src.application.order.dto.order import OrderDTO
from src.application.order.dto.orders import OrdersDTO
from src.application.order.enums import OrderPeriod, OrderStatus, OrderType
from src.application.order.uow import OrderUoW
from src.application.order.use_cases.archive_order import ArchiveOrder, ArchiveOrderHandler
from src.application.order.use_cases.create_order import CreateOrder, CreateOrderHandler
from src.application.order.use_cases.get_expired_orders import GetExpiredOrdersHandler
from src.application.order.use_cases.get_expiring_orders import GetExpiringOrders, GetExpiringOrdersHandler
from src.application.order.use_cases.get_order import GetOrder, GetOrderHandler
from src.application.order.use_cases.get_orders import GetOrders, GetOrdersHandler
from src.application.order.use_cases.get_user_subscription import GetUserSubscription, GetUserSubscriptionHandler
from src.application.order.use_cases.set_order_autorenew import SetOrderAutorenew, SetOrderAutorenewHandler
from src.application.order.use_cases.update_order_expiring import UpdateOrderExpiring, UpdateOrderExpiringHandler
from src.application.proxy.dto.proxy import ProxyDTO
from src.domain.common.constants import Empty, OrderBy


class OrderService:
    def __init__(
        self,
        *,
        uow: OrderUoW,
    ) -> None:
        self._uow = uow

    async def create_order(
        self,
        tg_id: int,
        order_type: OrderType,
        order_summ: float,
        category_id: int,
        period: OrderPeriod,
        country_id: int,
        provider_id: int,
        proxies: list[ProxyDTO],
        site_id: int,
        vpn_server_id: int | None,
        expiring_on: datetime.datetime,
    ) -> OrderDTO:
        """
        Создание заказа
        """
        command = CreateOrder(
            buyer_tg_id=tg_id,
            order_type=order_type,
            order_summ=order_summ,
            category_id=category_id,
            period=period,
            country_id=country_id,
            provider_id=provider_id,
            proxies=proxies,
            site_id=site_id,
            vpn_server_id=vpn_server_id,
            expiring_on=expiring_on,
        )
        return await CreateOrderHandler(uow=self._uow)(command=command)

    async def get_order_by_id(self, order_id: int) -> OrderDTO:
        """Получение заказа по id"""

        command = GetOrder(order_id=order_id)
        return await GetOrderHandler(uow=self._uow)(command=command)

    async def get_orders(
        self,
        tg_user_id: int | Empty = Empty.UNSET,
        offset: int | Empty = Empty.UNSET,
        limit: int | Empty = Empty.UNSET,
        order_type: OrderType | str = OrderType.proxy,
        order_by: OrderBy = OrderBy.ASC,
        order_status: OrderStatus | str = OrderStatus.active,
    ) -> OrdersDTO:
        """Получаем заказы по фильтрам"""

        if isinstance(order_type, str):
            order_type = getattr(OrderType, order_type)
        if isinstance(order_status, str):
            order_status = getattr(OrderStatus, order_status)

        query = GetOrders(
            tg_user_id=tg_user_id,
            offset=offset,
            limit=limit,
            order_type=order_type,
            order_by=order_by,
            order_status=order_status,
        )
        return await GetOrdersHandler(uow=self._uow)(query=query)

    async def get_user_subscription_order(self, tg_user_id: int):
        """Получаем подписку пользователя"""

        command = GetUserSubscription(tg_user_id=tg_user_id)
        return await GetUserSubscriptionHandler(uow=self._uow)(command=command)

    async def get_expiring_orders(self, autorenew: bool = False) -> list[OrderDTO]:
        """Получаем заканчивающиеся заказы"""

        command = GetExpiringOrders(autorenew)
        return await GetExpiringOrdersHandler(uow=self._uow)(command=command)

    async def get_expired_orders(self) -> list[OrderDTO]:
        """Получаем закончившиеся заказы"""

        return await GetExpiredOrdersHandler(uow=self._uow)()

    async def archive_order(self, order_id: int) -> OrderDTO:
        """Архивирование заказа"""

        command = ArchiveOrder(order_id=order_id)
        return await ArchiveOrderHandler(uow=self._uow)(command=command)

    async def add_allowed_ip(self, user_tg_id: int, order_id: int, ip_address: str) -> None:
        """Добавляем разрешенный ip к заказу"""

        # command = AddAllowedIp(tg_user_id=user_tg_id, order_id=order_id, ip_address=ip_address)
        ...
        # TODO Дописать

    async def change_proxy_in_order(self, order_id: int, old_proxy_id: int, new_proxy_id: int) -> None:
        """Заменяем прокси в заказе"""

        # command = AddAllowedIp(tg_user_id=user_tg_id, order_id=order_id, ip_address=ip_address)
        ...
        # TODO Дописать

    async def update_order_expiring(self, order_id: int, expiring_on: datetime.datetime) -> None:
        """Обновляем срок действия заказа"""

        command = UpdateOrderExpiring(order_id=order_id, expiring_on=expiring_on)
        return await UpdateOrderExpiringHandler(uow=self._uow)(command=command)

    async def set_order_autorenew(self, order_id: int, autorenew: bool):
        """Включаем/выключаем автопродление заказа"""

        command = SetOrderAutorenew(order_id, autorenew)
        return SetOrderAutorenewHandler(uow=self._uow)(command=command)
